前言
在JDK1.5以上版本中,提供了CopyOnWriteArrayList,CopyOnWriteArraySet两种并发容器。采用读写分离的思想(读操作在元数据中操作,写操作则在副本中操作),降低锁冲突,提高并发性。
原理剖析
CopyOnWriteArrayList 部分JDK源码:public class CopyOnWriteArrayList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
private static final long serialVersionUID = 8673264195747942595L;
/** The lock protecting all mutators */
transient final ReentrantLock lock = new ReentrantLock();
/** The array, accessed only via getArray/setArray. */
private volatile transient Object[] array;
/**
* Gets the array. Non-private so as to also be accessible
* from CopyOnWriteArraySet class.
*/
final Object[] getArray() {
return array;
}
/**
* Sets the array.
*/
final void setArray(Object[] a) {
array = a;
}
/**
* 读取操作(没有加锁)
*/
public E get(int index) {
return (E)(getArray()[index]);
}
/**
*写操作(加锁的目的:防止并发量大时,产生过多的元数据副本,耗内存)
*/
public boolean add(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
//对元数据进行拷贝
Object[] newElements = Arrays.copyOf(elements, len + 1);
newElements[len] = e;//操作副本
setArray(newElements);//修改元数组引用为副本引用
return true;
} finally {
lock.unlock();
}
}
}
总结
对于读多写少的场景(例如:缓存),可以有效减少锁冲突,提示系统并发能力。